package com.ylw.project.compile;

import com.ylw.project.JavaDomain;
import com.ylw.project.Tools;
import com.ylw.util.Config;
import org.apache.log4j.Logger;

import java.util.*;
import java.util.concurrent.*;

/**
 * 系统属性
 */
public class ProjectSystem {

    private static final Logger logger = Logger.getLogger(ProjectSystem.class);


    /**
     * //需要编译的java文件
     */
    private final static ConcurrentMap<String, Vector<JavaDomain>> needCompile = new ConcurrentHashMap();


    /**
     * 项目java文件锁 用来记录java文件数量 在javahandler里面 用来判断该项目的java文件是否都处理完成
     * 感觉这个都不需要并发map  这个目前只在初始化的时候用到 即在主线程用到
     * <p>
     * 让该项目的编译线程，等待该项目的所有java文件都被handler
     * <p>
     * CountDownLatch：一个或者多个线程，等待其他多个线程完成某件事情之后才能执行；  这个在等待线程里面调用await方法
     * CyclicBarrier：多个线程互相等待，直到到达同一个同步点，再继续一起执行。  这个直接在线程里面调用await方法
     */
    private final static ConcurrentMap<String, CountDownLatch> countJava = new ConcurrentHashMap();


    /**
     * 当编译线程完成后 的标识符
     */
    private final static Map<String, CountDownLatch> startsignal = new HashMap();

    /**
     * 这里 没法用，因为不知道需要编译的java文件数量
     * 锁用来判断  当该java需要编译时，让需要编译的java线程等待 编译java文件的线程完成，继续执行 copy操作
     * 让该项目的所有需要编译的java 文件复制线程等待编译线程完成
     */
    private final static ConcurrentMap<String, CyclicBarrier> countCompile = new ConcurrentHashMap();

    /**
     * 编译线程
     */
    private final static ConcurrentMap<String, Runnable> complierTasks = new ConcurrentHashMap();


    private final static ThreadPoolExecutor pool = (ThreadPoolExecutor) Executors.newCachedThreadPool();

    public static ConcurrentMap<String, Vector<JavaDomain>> getNeedCompile() {
        return needCompile;
    }

    /**
     * 激活编译线程
     *
     * @param projectName
     */
    public static void activeCompileTask(final String projectName) {
        if (!complierTasks.containsKey(projectName)) {
            synchronized (ProjectSystem.class) {
                if (!complierTasks.containsKey(projectName)) {
                    complierTasks.put(projectName, new Runnable() {
                        @Override
                        public void run() {
                            /**
                             * 等待该项目的java文件handler完成
                             */
                            try {
                                logger.info("waiting add java filecharset");
                                countJava.get(projectName).await();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            Vector<JavaDomain> v = needCompile.get(projectName);
                            //加上tomcat的jar包
                            String tomcatLib = (String) Config.getPropertValue("tomcat.lib.path").get(0);
                            String classPath = "";
                            if(Tools.isMacOs()) {
                                classPath= CompileTools.getAllJarPath(tomcatLib) + ":" + CompileTools.getAllJarPath(Tools.getLibRealPath(v.get(0).getSourcePath())) + ":" + v.get(0).getCompileProjectRootPath();
                            }else{
                                classPath= CompileTools.getAllJarPath(tomcatLib) + ";" + CompileTools.getAllJarPath(Tools.getLibRealPath(v.get(0).getSourcePath())) + ";" + v.get(0).getCompileProjectRootPath();
                            }

                            String destination = v.get(0).getCompileProjectRootPath();
                            List needCompiles = new ArrayList();

                            for(JavaDomain domain: v){
                                needCompiles.add(domain.getSourcePath());
                            }

                            CompileTools.compile(needCompiles, classPath, destination);
                            startsignal.get(projectName).countDown();
                        }
                    });
                    getPool().execute(complierTasks.get(projectName));
                }
            }
        }
    }


    public static ThreadPoolExecutor getPool() {
        return pool;
    }


    public static void addCountJava(String projectName, Integer num) {
        countJava.put(projectName, new CountDownLatch(num));
        startsignal.put(projectName, new CountDownLatch(1));
    }

    public static CountDownLatch getCountJava(String projectName) {
        return countJava.get(projectName);
    }

    public static CountDownLatch getStartSignal(String projectName) {
        return startsignal.get(projectName);
    }

    public static void addCountCompile(String projectName, Integer num) {
        countCompile.put(projectName, new CyclicBarrier(num));
    }


    /**
     * 通过java路径创建一个同步的vector容器
     *
     * @param domain
     * @return
     */
    public static boolean addToCompile(String projectName, JavaDomain domain) {
        if (ProjectSystem.getNeedCompile().containsKey(projectName)) {
            ProjectSystem.getNeedCompile().get(projectName).add(domain);
            return true;
        } else {
            Vector<JavaDomain> v = null;
            synchronized (ProjectSystem.class) {//选择同步该项目名称不知道行不行
                if (!ProjectSystem.getNeedCompile().containsKey(projectName)) {
                    v = new Vector();
                    ProjectSystem.getNeedCompile().put(projectName, v);
                }
                v.add(domain);
            }

            return true;
        }
    }
}
